<template>
  <!-- 加载失败 -->
  <div class="icc-monitor__fail"
    v-if="playerLoadFail"
    :style="playerStyle"
    @click="$emit('clickPlayer')"
  >
    <ArkIconFont icon="icon-ishipinshixiao" class="text-slate-500" :style="{ 'font-size': playerIconSize + 'px' }"/>

    <slot></slot>
  </div>

  <!-- 实时监控 与 监控回放 -->
  <div v-else muted="muted" @click="$emit('clickPlayer')"
    :id="`ws-${playerType}-player-${playerId}`"
  >
    <div class="icc-monitor__loading" v-if="playerNoLoadIcon">
      <ArkIconFont icon="icon-shipinbofang" class="text-slate-500" :style="{ 'font-size': playerIconSize + 'px' }"/>
    </div>

    <slot></slot>
  </div>

  <!--云台控制器-->
  <!--<div id="ws-pan-tilt" />-->
</template>

<script>
import {defineComponent} from 'vue';
import {v4 as uuidv4} from 'uuid';
import dayjs from 'dayjs';
import PlayerManager from './dependence/PlayerManager.js';
import ArkIconFont from "@/components/ark-component-v1/ark-iconfont/ArkIconFont.vue";

/**
 * ICC开放平台：https://open-icc.dahuatech.com/#/home
 *  - 考虑到多个监控需要分组同时播放的情况，此组件内的监控不能自动播放，需要外部手动触发播放
 *  - 坑：初始化回调只会在首次初始化完成后唯一调用一次！注意初始化完成后才能手动触发播放
 *  - 手动触发：playerNoLoadIcon=false;realPlay();
 */
export default defineComponent({
  name: 'IccMonitorSolo',
  components: {ArkIconFont},
  emits: ['initPlayerAfter', 'clickPlayer'],
  props: {
    playerType: {
      type: String,
      default: 'real',
      validator(value) {
        return ['real', 'record'].includes(value);
      }
    },
    playerId: {
      type: String,
      default: uuidv4(),
    },
    useNginxProxy: {
      type: Boolean,
      default: false,
    },
    proxyServerIp: String,
    streamServerIp: String,
    playerObj: {
      type: Object,
      default: () => ({
        id: '1000016$1$0$1',
        isOnline: false
      }),
    },
    recordDate: {
      type: String,
      validator(value) {
        return dayjs(value, 'YYYY-MM-DD', true).isValid();
      }
    },
    showTopControlBar: {
      type: Boolean,
      default: false,
    },
    playerIconSize: {
      type: Number,
      default: 25,
    },
    playerStyle: {
      type: Object,
      default: () => ({
        width: '100%',
        height: '100%',
      }),
    },
  },
  data() {
    return {
      playerManager: null,
      playerNoLoadIcon: true,
      playerLoadFail: false,
    };
  },
  mounted() {
    this.initPlayer();
  },
  unmounted() {
    this.closePlayer();
  },
  methods: {
    initPlayer() {
      if (this.playerObj.isOnline === 0) {
        this.playerManager = null;
        this.playerLoadFail = true;
      } else {
        if (this.playerType === 'real') {
          this.playerManager = new PlayerManager({
            el: `ws-real-player-${this.playerId}`,
            type: 'real',
            num: 1,
            maxNum: 1,
            showControl: false,
            receiveMessageFromWSPlayer: this.playerCallback,
            pztEl: 'ws-pan-tilt',
            streamServerIp: this.streamServerIp,
            proxyServerIp: this.proxyServerIp,
            useNginxProxy: this.useNginxProxy,
          });
        } else if (this.playerType === 'record') {
          this.playerManager = new PlayerManager({
            el: `ws-record-player-${this.playerId}`,
            type: 'record',
            num: 1,
            maxNum: 1,
            showControl: false,
            receiveMessageFromWSPlayer: this.playerCallback,
          });
        }

        /**
         * 顶部工具栏功能配置
         * showIcons: {
         *  streamChangeSelect: true, // 主码流切换按钮
         *  talkIcon: true, // 对讲功能按钮
         *  localRecordIcon: true, // 本地录像功能按钮
         *  audioIcon: true, // 开启关闭声音按钮
         *  snapshotIcon: true, // 抓图按钮
         *  closeIcon: false, // 关闭视频按钮
         * },
         */

        // 修改播放器样式
        this.renderPlayerStyle();

        if (!this.showTopControlBar) {
          // 隐藏顶部工具栏
          this.hiddenTopControlBar();
        }
      }
    },
    playerCallback(method, data, err) {
      switch (method) {
        case 'initializationCompleted': // 初始化播放器成功
          this.$emit('initPlayerAfter');
          break;
        case 'realSuccess': // 实时预览成功
          break;
        case 'realError': // 实时预览失败
          this.playerLoadFail = true;
          break;
        case 'recordSuccess': // 录像回放成功
          break;
        case 'recordError': // 录像回放失败
          this.playerLoadFail = true;
          break;
        case 'talkError': // 对讲失败
          break;
        case 'selectWindowChanged': // 切换窗口回调
          break;
        case 'windowNumChanged': // 显示窗口数量变化回调
          break;
        case 'statusChanged': // 窗口视频状态变化回调
          break;
        case 'closeVideo': // 非视频切换而引起的视频关闭
          break;
        case 'errorInfo':
          console.error('大华视频错误信息：', data.errorInfo);
          this.playerLoadFail = true;
          break;
        default:
      }
    },
    renderPlayerStyle() {
      const wsPlayer = document.querySelector(`#ws-${this.playerType}-player-${this.playerId}`);
      Object.keys(this.playerStyle).forEach((item) => {
        if (wsPlayer.style) {
          wsPlayer.style[item] = this.playerStyle[item];
        }
      });
    },
    hiddenTopControlBar() {
      const topControlBars = document.querySelectorAll(`#ws-${this.playerType}-player-${this.playerId} .top-control-bar`);

      // 将顶部控制框移出可见框，不可删除受到大华视频初始化影响
      topControlBars.forEach((topControlBar) => {
        topControlBar.style.transform = 'translateY(-50px)';
      });
    },

    // 以下方法均可能被外部调用
    closePlayer(playerManager) {
      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }
      if (!playerIns) return;

      playerIns.close();
    },
    realPlay(playerManager, playerObj) {
      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }
      if (!playerIns) return;

      // 若传入playerObj对象，则为传入对象进行操作
      let playerChannel = this.playerObj;
      if (playerObj) {
        playerChannel = playerObj;
      }
      if (!playerChannel) return;

      playerIns.playRealVideo({
        channelList: [playerChannel],
        streamType: '2', // 默认用辅码流播放
      });
    },
    recordPlay(recordDate, playerManager, playerObj) {
      // 若传入recordDate，则为传入的值进行操作
      let date = this.recordDate;
      if (recordDate) {
        date = recordDate;
      }
      if (!date) return;

      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }
      if (!playerIns) return;

      // 若传入playerObj对象，则为传入对象进行操作
      let playerChannel = this.playerObj;
      if (playerObj) {
        playerChannel = playerObj;
      }
      if (!playerChannel) return;

      // 格式化开始和结束时间，并转为时间戳
      let startTime = dayjs(date).startOf('day').format('YYYY-MM-DD HH:mm:ss');
      startTime = dayjs(startTime).format('X');
      let endTime = dayjs(date).endOf('day').format('YYYY-MM-DD HH:mm:ss');
      endTime = dayjs(endTime).format('X');

      playerIns.playRecordVideo({
        channelList: [playerChannel],
        streamType: '2', // 默认用辅码流播放
        startTime: startTime,
        endTime: endTime,
        recordSource: 1,
        recordType: '0',
      });
    },
    playerAdapter(adapter, playerManager) {
      // 适应列表中不存在的不可取
      const existAdapter =
        adapter && (adapter === 'selfAdaption' || adapter === 'stretching');
      if (!existAdapter) return;

      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }

      // playerManager为空则返回
      if (!playerIns) return;

      playerIns.setPlayerAdapter(adapter);
    },
    playerFullScreen(playerManager) {
      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }

      // playerManager为空则返回
      if (!playerIns) return;

      playerIns.setFullScreen();
    },
    pauseToPlay(playerManager) {
      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }

      // playerManager为空则返回
      if (!playerIns) return;

      // 实时预览不支持该功能
      if (playerIns.type === 'real') return;

      // 非播放状态下才可操作
      const selectPlayerItem = playerIns.player.playerList[0];
      if (selectPlayerItem.status === 'playing') return;

      playerIns.play();
    },
    playToPause(playerManager) {
      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }

      // playerManager为空则返回
      if (!playerIns) return;

      // 实时预览不支持该功能
      if (playerIns.type === 'real') return;

      // 播放状态下才可操作
      const selectPlayerItem = playerIns.player.playerList[0];
      if (selectPlayerItem.status !== 'playing') return;

      playerIns.pause();
    },
    playSpeed(speed, playerManager) {
      // 倍速列表中不存在的速度不可取
      const speedList = [
        '0.125',
        '0.25',
        '0.5',
        '1',
        '1.25',
        '1.5',
        '2',
        '4',
        '8',
      ];
      const existSpeed = speed && speedList.includes(speed.toString());
      if (!existSpeed) return;

      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }

      // playerManager为空则返回
      if (!playerIns) return;

      // 实时预览不支持该功能
      if (playerIns.type === 'real') return;

      // 播放状态下才可操作
      const selectPlayerItem = playerIns.player.playerList[0];
      if (selectPlayerItem.status !== 'playing') return;

      playerIns.playSpeed(speed);
    },
    jumpPlayByTime(jumpTime, playerManager) {
      // 录像回放跳转时间格式不正确则返回
      const reg = /^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;
      const existJumpTime = jumpTime && reg.test(jumpTime);
      if (!existJumpTime) return;

      // 若传入playerManager对象，则为传入对象进行操作
      let playerIns = this.playerManager;
      if (playerManager) {
        playerIns = playerManager;
      }

      // playerManager为空则返回
      if (!playerIns) return;

      // 实时预览不支持该功能
      if (playerIns.type === 'real') return;

      // 播放状态下才可操作
      const selectPlayerItem = playerIns.player.playerList[0];
      if (selectPlayerItem.status !== 'playing') return;

      playerIns.jumpPlayByTime(jumpTime);
    },
  }
});
</script>

<style scoped>
.ws-player {
  position: relative;

  .wsplayer-item {
    border: none !important;
  }
}

.icc-monitor__fail {
  @apply flex justify-center items-center relative bg-[#1C2834];
}

.icc-monitor__loading {
  @apply absolute top-0 bottom-0 left-0 right-0 flex justify-center items-center;
}
</style>